/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * ImageEditorWindow.java
 *
 * Created on Jun 20, 2011, 11:37:58 PM
 */
package MainProgram.UI;

import Global.CImageIO;
import Global.FileFinder;
import MainProgram.Console.ErrorConsole;
import MainProgram.ProgramLaunchers.ProgramLauncher;
import Threading.BackgroundTaskRunner;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dialog.ModalityType;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.filechooser.FileFilter;
import org.jdesktop.application.Action;
import org.jdesktop.application.Application;

/**
 *
 * @author Stephen
 */
public class ImageEditorWindow extends javax.swing.JFrame
{
    /** Creates new form ImageEditorWindow */
    public ImageEditorWindow()
    {
        initComponents();
        
        setIconImage(ProgramLauncher.getProgramIcon(this));
    }
    
    private BufferedImage m_image = new BufferedImage(250, 250, BufferedImage.TYPE_INT_ARGB);
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        v_imagePanelScrollPane = new javax.swing.JScrollPane();
        v_imagePanel = new javax.swing.JPanel();
        v_imageDrawingPanel = new javax.swing.JPanel()
        {
            public void paint(Graphics graphics)
            {
                Graphics2D g = (Graphics2D)graphics;
                super.paint(g);
                g.drawImage(m_image, 2, 2, this);
            }
        };
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();
        jMenuItem2 = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jMenuItem3 = new javax.swing.JMenuItem();
        jSeparator2 = new javax.swing.JPopupMenu.Separator();
        jMenuItem4 = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenuItem5 = new javax.swing.JMenuItem();
        jMenuItem6 = new javax.swing.JMenuItem();
        jMenuItem7 = new javax.swing.JMenuItem();
        jMenu5 = new javax.swing.JMenu();
        jMenuItem12 = new javax.swing.JMenuItem();
        jMenu3 = new javax.swing.JMenu();
        jMenu6 = new javax.swing.JMenu();
        jMenuItem13 = new javax.swing.JMenuItem();
        jMenuItem11 = new javax.swing.JMenuItem();
        jMenuItem14 = new javax.swing.JMenuItem();
        jMenuItem15 = new javax.swing.JMenuItem();
        jMenu8 = new javax.swing.JMenu();
        jMenuItem19 = new javax.swing.JMenuItem();
        jSeparator6 = new javax.swing.JPopupMenu.Separator();
        jMenuItem22 = new javax.swing.JMenuItem();
        jMenuItem23 = new javax.swing.JMenuItem();
        jSeparator9 = new javax.swing.JPopupMenu.Separator();
        jMenuItem25 = new javax.swing.JMenuItem();
        jMenuItem26 = new javax.swing.JMenuItem();
        jMenu4 = new javax.swing.JMenu();
        jMenuItem10 = new javax.swing.JMenuItem();
        jSeparator4 = new javax.swing.JPopupMenu.Separator();
        jMenuItem9 = new javax.swing.JMenuItem();
        jSeparator3 = new javax.swing.JPopupMenu.Separator();
        jMenuItem8 = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
        setTitle("Imaging Toolbox");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        v_imagePanelScrollPane.setName("v_imagePanelScrollPane"); // NOI18N

        v_imagePanel.setName("v_imagePanel"); // NOI18N
        v_imagePanel.setLayout(new java.awt.GridBagLayout());

        v_imageDrawingPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        v_imageDrawingPanel.setName("v_imageDrawingPanel"); // NOI18N
        v_imageDrawingPanel.setPreferredSize(new java.awt.Dimension(250, 250));
        v_imageDrawingPanel.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                v_imageDrawingPanelMousePressed(evt);
            }
            public void mouseReleased(java.awt.event.MouseEvent evt) {
                v_imageDrawingPanelMouseReleased(evt);
            }
        });
        v_imageDrawingPanel.addMouseMotionListener(new java.awt.event.MouseMotionAdapter() {
            public void mouseDragged(java.awt.event.MouseEvent evt) {
                v_imageDrawingPanelMouseDragged(evt);
            }
        });

        javax.swing.GroupLayout v_imageDrawingPanelLayout = new javax.swing.GroupLayout(v_imageDrawingPanel);
        v_imageDrawingPanel.setLayout(v_imageDrawingPanelLayout);
        v_imageDrawingPanelLayout.setHorizontalGroup(
            v_imageDrawingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 246, Short.MAX_VALUE)
        );
        v_imageDrawingPanelLayout.setVerticalGroup(
            v_imageDrawingPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 246, Short.MAX_VALUE)
        );

        v_imagePanel.add(v_imageDrawingPanel, new java.awt.GridBagConstraints());

        v_imagePanelScrollPane.setViewportView(v_imagePanel);

        jMenuBar1.setName("jMenuBar1"); // NOI18N

        jMenu1.setText("File");
        jMenu1.setName("jMenu1"); // NOI18N

        javax.swing.ActionMap actionMap = org.jdesktop.application.Application.getInstance().getContext().getActionMap(ImageEditorWindow.class, this);
        jMenuItem1.setAction(actionMap.get("Save")); // NOI18N
        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance().getContext().getResourceMap(ImageEditorWindow.class);
        jMenuItem1.setText(resourceMap.getString("jMenuItem1.text")); // NOI18N
        jMenuItem1.setName("jMenuItem1"); // NOI18N
        jMenu1.add(jMenuItem1);

        jMenuItem2.setAction(actionMap.get("SaveAs")); // NOI18N
        jMenuItem2.setText(resourceMap.getString("jMenuItem2.text")); // NOI18N
        jMenuItem2.setName("jMenuItem2"); // NOI18N
        jMenu1.add(jMenuItem2);

        jSeparator1.setName("jSeparator1"); // NOI18N
        jMenu1.add(jSeparator1);

        jMenuItem3.setAction(actionMap.get("Open")); // NOI18N
        jMenuItem3.setText(resourceMap.getString("jMenuItem3.text")); // NOI18N
        jMenuItem3.setName("jMenuItem3"); // NOI18N
        jMenu1.add(jMenuItem3);

        jSeparator2.setName("jSeparator2"); // NOI18N
        jMenu1.add(jSeparator2);

        jMenuItem4.setAction(actionMap.get("Exit")); // NOI18N
        jMenuItem4.setText(resourceMap.getString("jMenuItem4.text")); // NOI18N
        jMenuItem4.setName("jMenuItem4"); // NOI18N
        jMenu1.add(jMenuItem4);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Edit");
        jMenu2.setName("jMenu2"); // NOI18N

        jMenuItem5.setText("Cut");
        jMenuItem5.setName("jMenuItem5"); // NOI18N
        jMenu2.add(jMenuItem5);

        jMenuItem6.setText("Copy");
        jMenuItem6.setName("jMenuItem6"); // NOI18N
        jMenu2.add(jMenuItem6);

        jMenuItem7.setText("Paste");
        jMenuItem7.setName("jMenuItem7"); // NOI18N
        jMenu2.add(jMenuItem7);

        jMenuBar1.add(jMenu2);

        jMenu5.setAction(actionMap.get("OpenWalkthroughOptions")); // NOI18N
        jMenu5.setText("Options");
        jMenu5.setName("jMenu5"); // NOI18N

        jMenuItem12.setAction(actionMap.get("OpenProgramSettings")); // NOI18N
        jMenuItem12.setText(resourceMap.getString("jMenuItem12.text")); // NOI18N
        jMenuItem12.setName("jMenuItem12"); // NOI18N
        jMenu5.add(jMenuItem12);

        jMenuBar1.add(jMenu5);

        jMenu3.setText("Filters");
        jMenu3.setName("jMenu3"); // NOI18N

        jMenu6.setText("Background");
        jMenu6.setName("jMenu6"); // NOI18N

        jMenuItem13.setText("White To Transparent");
        jMenuItem13.setName("jMenuItem13"); // NOI18N
        jMenuItem13.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem13ActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItem13);

        jMenuItem11.setText("Black To Transparent");
        jMenuItem11.setName("jMenuItem11"); // NOI18N
        jMenuItem11.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem11ActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItem11);

        jMenuItem14.setText("White To Black");
        jMenuItem14.setName("jMenuItem14"); // NOI18N
        jMenuItem14.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem14ActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItem14);

        jMenuItem15.setText("Black To White");
        jMenuItem15.setName("jMenuItem15"); // NOI18N
        jMenuItem15.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem15ActionPerformed(evt);
            }
        });
        jMenu6.add(jMenuItem15);

        jMenu3.add(jMenu6);

        jMenuBar1.add(jMenu3);

        jMenu8.setText(resourceMap.getString("jMenu8.text")); // NOI18N
        jMenu8.setName("jMenu8"); // NOI18N

        jMenuItem19.setAction(actionMap.get("ShowErrorConsole")); // NOI18N
        jMenuItem19.setText(resourceMap.getString("jMenuItem19.text")); // NOI18N
        jMenuItem19.setName("jMenuItem19"); // NOI18N
        jMenu8.add(jMenuItem19);

        jSeparator6.setName("jSeparator6"); // NOI18N
        jMenu8.add(jSeparator6);

        jMenuItem22.setText(resourceMap.getString("jMenuItem22.text")); // NOI18N
        jMenuItem22.setName("jMenuItem22"); // NOI18N
        jMenu8.add(jMenuItem22);

        jMenuItem23.setText(resourceMap.getString("jMenuItem23.text")); // NOI18N
        jMenuItem23.setName("jMenuItem23"); // NOI18N
        jMenu8.add(jMenuItem23);

        jSeparator9.setName("jSeparator9"); // NOI18N
        jMenu8.add(jSeparator9);

        jMenuItem25.setAction(actionMap.get("ShowChangelog")); // NOI18N
        jMenuItem25.setText(resourceMap.getString("jMenuItem25.text")); // NOI18N
        jMenuItem25.setName("jMenuItem25"); // NOI18N
        jMenu8.add(jMenuItem25);

        jMenuItem26.setText(resourceMap.getString("jMenuItem26.text")); // NOI18N
        jMenuItem26.setName("jMenuItem26"); // NOI18N
        jMenu8.add(jMenuItem26);

        jMenuBar1.add(jMenu8);

        jMenu4.setText("Help");
        jMenu4.setName("jMenu4"); // NOI18N

        jMenuItem10.setText("Help Contents");
        jMenuItem10.setName("jMenuItem10"); // NOI18N
        jMenu4.add(jMenuItem10);

        jSeparator4.setName("jSeparator4"); // NOI18N
        jMenu4.add(jSeparator4);

        jMenuItem9.setText("Check For Updates");
        jMenuItem9.setName("jMenuItem9"); // NOI18N
        jMenu4.add(jMenuItem9);

        jSeparator3.setName("jSeparator3"); // NOI18N
        jMenu4.add(jSeparator3);

        jMenuItem8.setText("About");
        jMenuItem8.setName("jMenuItem8"); // NOI18N
        jMenu4.add(jMenuItem8);

        jMenuBar1.add(jMenu4);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(v_imagePanelScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 731, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(v_imagePanelScrollPane, javax.swing.GroupLayout.DEFAULT_SIZE, 563, Short.MAX_VALUE)
        );

        java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
        setBounds((screenSize.width-747)/2, (screenSize.height-622)/2, 747, 622);
    }// </editor-fold>//GEN-END:initComponents

    private void formWindowClosing(java.awt.event.WindowEvent evt)//GEN-FIRST:event_formWindowClosing
    {//GEN-HEADEREND:event_formWindowClosing
        Exit();
    }//GEN-LAST:event_formWindowClosing

    private void jMenuItem13ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem13ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem13ActionPerformed
        Runnable runner = new Runnable()
        {
            @Override
            public void run()
            {
                for (int x = 0; x < m_image.getWidth(); x++)
                {
                    for (int y = 0; y < m_image.getHeight(); y++)
                    {
                        if(BackgroundTaskRunner.s_shouldStopBT)
                            return;
                        Color color = new Color(m_image.getRGB(x, y));
                        int redDif = 255 - color.getRed();
                        int greenDif = 255 - color.getGreen();
                        int blueDif = 255 - color.getBlue();
                        double highestRorGorBDif = Math.max(blueDif, Math.max(greenDif, redDif));
                        double scaleFactor = 255D / highestRorGorBDif;
                        m_image.setRGB(x, y, new Color(255 - (int) (redDif * scaleFactor), 255 - (int) (greenDif * scaleFactor), 255 - (int) (blueDif * scaleFactor), (int) (color.getAlpha() / scaleFactor)).getRGB());                        
                    }
                }
            }
        };
        
        BackgroundTaskRunner.runInBackground(this, "Weakening color and weakening alpha...", runner, true);
        v_imageDrawingPanel.repaint();
    }//GEN-LAST:event_jMenuItem13ActionPerformed

    private void jMenuItem11ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem11ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem11ActionPerformed
        Runnable runner = new Runnable()
        {
            @Override
            public void run()
            {
                for (int x = 0; x < m_image.getWidth(); x++)
                {
                    for (int y = 0; y < m_image.getHeight(); y++)
                    {
                        if(BackgroundTaskRunner.s_shouldStopBT)
                            return;
                        Color color = new Color(m_image.getRGB(x, y));
                        int highestRorGorBDif = Math.max(color.getBlue(), Math.max(color.getGreen(), color.getRed()));
                        double scaleFactor = 255D / highestRorGorBDif;
                        m_image.setRGB(x, y, new Color((int) (color.getRed() * scaleFactor), (int) (color.getGreen() * scaleFactor), (int) (color.getBlue() * scaleFactor), (int) (color.getAlpha() / scaleFactor)).getRGB());
                    }
                }
            }
        };
        
        BackgroundTaskRunner.runInBackground(this, "Strengthening color and weakening alpha...", runner, true);
        v_imageDrawingPanel.repaint();
    }//GEN-LAST:event_jMenuItem11ActionPerformed

    private void jMenuItem14ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem14ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem14ActionPerformed
        Runnable runner = new Runnable()
        {
            @Override
            public void run()
            {
                for (int x = 0; x < m_image.getWidth(); x++)
                {
                    for (int y = 0; y < m_image.getHeight(); y++)
                    {
                        if(BackgroundTaskRunner.s_shouldStopBT)
                            return;
                        Color color = new Color(m_image.getRGB(x, y));
                        int redDif = 255 - color.getRed();
                        int greenDif = 255 - color.getGreen();
                        int blueDif = 255 - color.getBlue();
                        double highestRorGorBDif = Math.max(blueDif, Math.max(greenDif, redDif));
                        double scaleFactor = 255D / highestRorGorBDif;
                        m_image.setRGB(x, y, new Color(255 - (int) (redDif * scaleFactor), 255 - (int) (greenDif * scaleFactor), 255 - (int) (blueDif * scaleFactor), (int) (color.getAlpha() / scaleFactor)).getRGB());                        
                    }
                }
                m_image.getGraphics().drawImage(m_image, 0, 0, Color.black, v_imageDrawingPanel);
            }
        };
        
        BackgroundTaskRunner.runInBackground(this, "Weakening color and weakening alpha, then inserting black background behind image...", runner, true);
        v_imageDrawingPanel.repaint();
    }//GEN-LAST:event_jMenuItem14ActionPerformed

    private void jMenuItem15ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem15ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem15ActionPerformed
        Runnable runner = new Runnable()
        {
            @Override
            public void run()
            {
                for (int x = 0; x < m_image.getWidth(); x++)
                {
                    for (int y = 0; y < m_image.getHeight(); y++)
                    {
                        if(BackgroundTaskRunner.s_shouldStopBT)
                            return;
                        Color color = new Color(m_image.getRGB(x, y));
                        int highestRorGorBDif = Math.max(color.getBlue(), Math.max(color.getGreen(), color.getRed()));
                        double scaleFactor = 255D / highestRorGorBDif;
                        m_image.setRGB(x, y, new Color((int) (color.getRed() * scaleFactor), (int) (color.getGreen() * scaleFactor), (int) (color.getBlue() * scaleFactor), (int) (color.getAlpha() / scaleFactor)).getRGB());
                    }
                }
                m_image.getGraphics().drawImage(m_image, 0, 0, Color.white, v_imageDrawingPanel);
            }
        };
        
        BackgroundTaskRunner.runInBackground(this, "Strengthening color and weakening alpha, then inserting white background behind image...", runner, true);
        v_imageDrawingPanel.repaint();
    }//GEN-LAST:event_jMenuItem15ActionPerformed

    Point m_origScrollPoint = new Point(0,0);
    Point m_lastPoint = new Point(0,0);
    
    private Point LimitedImagePoint(Point p)
    {
        Point r = new Point(p.x + v_imagePanelScrollPane.getViewport().getWidth() < m_image.getWidth() ? p.x : m_image.getWidth() - 1 - v_imagePanelScrollPane.getViewport().getWidth(),p.y + v_imagePanelScrollPane.getViewport().getHeight() < m_image.getHeight() ? p.y : m_image.getHeight() - 1 - v_imagePanelScrollPane.getViewport().getHeight());
        return new Point(r.x > 0 ? r.x : 0, r.y > 0 ? r.y : 0);
    }
    
    private void v_imageDrawingPanelMouseDragged(java.awt.event.MouseEvent evt)//GEN-FIRST:event_v_imageDrawingPanelMouseDragged
    {//GEN-HEADEREND:event_v_imageDrawingPanelMouseDragged
        if (m_origScrollPoint != null && evt.getButton() != evt.BUTTON1 && (v_imageDrawingPanel.getWidth() > v_imagePanelScrollPane.getWidth() || v_imageDrawingPanel.getHeight() > v_imagePanelScrollPane.getHeight()))
        {
            if(m_lastPoint == null) //Mouse held from another panel
                return;
            v_imageDrawingPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            v_imagePanelScrollPane.getViewport().setViewPosition(LimitedImagePoint(new Point(m_origScrollPoint.x + (m_lastPoint.x - evt.getXOnScreen()), m_origScrollPoint.y + (m_lastPoint.y - evt.getYOnScreen()))));
        }
    }//GEN-LAST:event_v_imageDrawingPanelMouseDragged

    private void v_imageDrawingPanelMousePressed(java.awt.event.MouseEvent evt)//GEN-FIRST:event_v_imageDrawingPanelMousePressed
    {//GEN-HEADEREND:event_v_imageDrawingPanelMousePressed
        if(evt.getButton() != MouseEvent.BUTTON1)
        {
            m_origScrollPoint = v_imagePanelScrollPane.getViewport().getViewPosition();
            m_lastPoint = evt.getLocationOnScreen();
        }
    }//GEN-LAST:event_v_imageDrawingPanelMousePressed

    private void v_imageDrawingPanelMouseReleased(java.awt.event.MouseEvent evt)//GEN-FIRST:event_v_imageDrawingPanelMouseReleased
    {//GEN-HEADEREND:event_v_imageDrawingPanelMouseReleased
        v_imageDrawingPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
    }//GEN-LAST:event_v_imageDrawingPanelMouseReleased

    private File m_lastSaveLocForCurrentImage = null;
    
    @Action
    public void Save()
    {
        if (m_lastSaveLocForCurrentImage != null)
        {
            CImageIO.SaveImageToFile(m_image, m_lastSaveLocForCurrentImage);
            JOptionPane.showMessageDialog(this, "Image saved to file!", "Image Saved", JOptionPane.INFORMATION_MESSAGE);
        }
        else
            SaveAs();
    }
    
    @Action
    public void SaveAs()
    {
        FileSave saver = new FileSave(this, "Select a save location", ".png", "PNG Image Files");
        String path = saver.getFilePath();
        if (path == null)
            return;

        if(!path.endsWith(".png"))
            path = path + ".png";

        path = new File(path).getAbsolutePath();

        m_lastSaveLocForCurrentImage = new File(path);
        CImageIO.SaveImageToFile(m_image, new File(path));
        JOptionPane.showMessageDialog(this, "Image saved to file!", "Image Saved", JOptionPane.INFORMATION_MESSAGE);
    }

    @Action
    public void Open()
    {
        ArrayList<FileFilter> filters = new ArrayList<FileFilter>();
        filters.add(FileOpen.CreateFilter("Loadable Image Files", new ArrayList<String>(Arrays.asList(".jpg", ".jpeg", ".png", ".gif", ".bmp"))));
        FileOpen open = new FileOpen(this, "Select an image to load", filters);
        if (open.getFilePath() == null)
            return;
        m_lastSaveLocForCurrentImage = null;
        Image loaded = CImageIO.LoadImageFromFile(open.getFile());
        BufferedImage finalImage = new BufferedImage(loaded.getWidth(null), loaded.getHeight(null), BufferedImage.TYPE_INT_ARGB);
        finalImage.getGraphics().drawImage(loaded, 0, 0, null);
        m_image = finalImage;
        v_imageDrawingPanel.setPreferredSize(new Dimension(finalImage.getWidth() + 4, finalImage.getHeight() + 4)); //Remember the border        
        v_imagePanel.doLayout();
        setSize(getWidth() + 1, getHeight() + 1); //Trigger draw panel resize
        setSize(getWidth() - 1, getHeight() - 1);
        v_imageDrawingPanel.repaint();
    }

    @Action
    public void Exit()
    {
        if(JOptionPane.showConfirmDialog(rootPane, "All unsaved work will be lost if you exit. Are you sure you want to exit?", "Confirm Exit",0) == 0)
            Application.getInstance().exit();
    }

    @Action
    public void OpenProgramSettings()
    {
        ProgramSettingsWindow settings = new ProgramSettingsWindow(this);
        settings.setLocationRelativeTo(this);
        settings.setVisible(true);
    }

    @Action
    public void ShowChangelog()
    {
        StringBuilder changelog = new StringBuilder();
        
        try
        {
            File changelogFile = FileFinder.FindChangelogFile();
            FileReader reader = new FileReader(changelogFile);
            BufferedReader bReader = new BufferedReader(reader);

            while (true)
            {
                String line = bReader.readLine();
                if (line == null)
                    break;
                changelog.append(line).append("\r\n");
            }
            
            reader.close();
            bReader.close();
        }
        catch(Exception ex)
        {
            changelog.append("[Error loading changelog: ").append(ex.toString()).append("]");
        }

        final JDialog dialog = new JDialog(ImageEditorWindow.this);
        dialog.setIconImage(ProgramLauncher.getProgramIcon(dialog));
        dialog.setTitle("Program Changelog");
        dialog.setModalityType(ModalityType.APPLICATION_MODAL);
        
        final JScrollPane scroll = new JScrollPane();
        
        JTextArea textArea = new JTextArea();
        textArea.setEditable(false);
        textArea.setText(changelog.toString());        
        scroll.setViewportView(textArea);
        
        JPanel buttons = new JPanel();
        final JButton button = new JButton(new AbstractAction("OK")
        {
            public void actionPerformed(ActionEvent e)
            {
                dialog.setVisible(false);
            }
        });
        buttons.add(button);        
        
        dialog.add(scroll, BorderLayout.CENTER);        
        dialog.add(buttons, BorderLayout.SOUTH);
        dialog.getRootPane().setDefaultButton(button);
        dialog.pack();
        dialog.setSize(750, 500);
        dialog.setLocationRelativeTo(ImageEditorWindow.this);
        dialog.addWindowListener(new WindowAdapter()
        {
            @Override
            public void windowOpened(WindowEvent e)
            {
                scroll.getVerticalScrollBar().getModel().setValue(0);
                scroll.getHorizontalScrollBar().getModel().setValue(0);
                button.requestFocus();
            }
        });
        
        dialog.setVisible(true);
        //The thread pauses here until dialog is closed
        dialog.dispose();
    }

    @Action
    public void ShowErrorConsole()
    {
        ErrorConsole.getConsole().setVisible(true);
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenu jMenu3;
    private javax.swing.JMenu jMenu4;
    private javax.swing.JMenu jMenu5;
    private javax.swing.JMenu jMenu6;
    private javax.swing.JMenu jMenu8;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItem10;
    private javax.swing.JMenuItem jMenuItem11;
    private javax.swing.JMenuItem jMenuItem12;
    private javax.swing.JMenuItem jMenuItem13;
    private javax.swing.JMenuItem jMenuItem14;
    private javax.swing.JMenuItem jMenuItem15;
    private javax.swing.JMenuItem jMenuItem19;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem22;
    private javax.swing.JMenuItem jMenuItem23;
    private javax.swing.JMenuItem jMenuItem25;
    private javax.swing.JMenuItem jMenuItem26;
    private javax.swing.JMenuItem jMenuItem3;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JMenuItem jMenuItem5;
    private javax.swing.JMenuItem jMenuItem6;
    private javax.swing.JMenuItem jMenuItem7;
    private javax.swing.JMenuItem jMenuItem8;
    private javax.swing.JMenuItem jMenuItem9;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JPopupMenu.Separator jSeparator2;
    private javax.swing.JPopupMenu.Separator jSeparator3;
    private javax.swing.JPopupMenu.Separator jSeparator4;
    private javax.swing.JPopupMenu.Separator jSeparator6;
    private javax.swing.JPopupMenu.Separator jSeparator9;
    private javax.swing.JPanel v_imageDrawingPanel;
    private javax.swing.JPanel v_imagePanel;
    private javax.swing.JScrollPane v_imagePanelScrollPane;
    // End of variables declaration//GEN-END:variables
}
